#include "Mutex.hpp"
#include "Sem.hpp"
#include <vector>

using namespace SemModlue;
using namespace MutexModlue;

static const int defaultcap = 5;

template <class T>
class RingQueue
{
public:
    RingQueue(int cap = defaultcap)
        :_cap(cap)
        ,_q(cap)
        ,_blank_sem(cap)
        ,_c_step(0)
        ,_data_sem(0)
        ,_p_step(0)
    {}

    void Equeue(const T& data)
    {
        _blank_sem.P();
        {
            LockGuard lockguard(_p_mutex);
            _q[_p_step++] = data;
            _p_step %= _cap;
        }
        _data_sem.V();
    }

    void Pop(T* out)
    {
        _data_sem.P();
        {
            LockGuard lockguard(_c_mutex);
            *out = _q[_c_step];
            _c_step++;
            _c_step %= _cap;
        }
        _blank_sem.V();
    }

private:
    std::vector<T> _q;
    int _cap;

    Sem _blank_sem;
    int _c_step;
    Sem _data_sem;
    int _p_step;
    
    Mutex _p_mutex;
    Mutex _c_mutex;

};